package com.qunar.dyds.util;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang.StringUtils;

public class ValidateUtil {

    // 移动： 134、135、136、137、138、139、147、150、151、152、157、158、159、182、187、188
    // 联通： 130、131、132、155、156、185、186
    // 电信： 133、153、180、189 　

    private static final Pattern mobilePattern = Pattern.compile("^1\\d{10}$");
    private static final Pattern emailPattern = Pattern
            .compile("^([a-zA-Z0-9_\\-\\.]+)@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.)|(([a-zA-Z0-9\\-]+\\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\\]?)$");

    /**
     * 检测邮箱是否合法
     * 
     * @param email 邮箱地址
     * @return 是否合法（合法-true 非法-false）
     */
    public static boolean isEmail(final String email) {
        if (null == email) {
            return false;
        }
        return emailPattern.matcher(email).matches();
    }

    /**
     * 检测手机号是否合法
     * 
     * @param mobile 手机号
     * @return 是否合法（合法-true 非法-false）
     */
    public static boolean isMobile(final String mobile) {
        if (null == mobile) {
            return false;
        }
        Matcher matcher = mobilePattern.matcher(mobile);
        return matcher.matches();
    }

    /**
     * 身份证验证地区编码
     */
    static final Map<String, String> areaCode = new HashMap<String, String>();
    static {
        areaCode.put("11", "北京");
        areaCode.put("12", "天津");
        areaCode.put("13", "河北");
        areaCode.put("14", "山西");
        areaCode.put("15", "内蒙古");
        areaCode.put("21", "辽宁");
        areaCode.put("22", "吉林");
        areaCode.put("23", "黑龙江");
        areaCode.put("31", "上海");
        areaCode.put("32", "江苏");
        areaCode.put("33", "浙江");
        areaCode.put("34", "安徽");
        areaCode.put("35", "福建");
        areaCode.put("36", "江西");
        areaCode.put("37", "山东");
        areaCode.put("41", "河南");
        areaCode.put("42", "湖北");
        areaCode.put("43", "湖南");
        areaCode.put("44", "广东");
        areaCode.put("45", "广西");
        areaCode.put("46", "海南");
        areaCode.put("50", "重庆");
        areaCode.put("51", "四川");
        areaCode.put("52", "贵州");
        areaCode.put("53", "云南");
        areaCode.put("54", "西藏");
        areaCode.put("61", "陕西");
        areaCode.put("62", "甘肃");
        areaCode.put("63", "青海");
        areaCode.put("64", "宁夏");
        areaCode.put("65", "新疆");
        areaCode.put("71", "台湾");
        areaCode.put("81", "香港");
        areaCode.put("82", "澳门");
        areaCode.put("91", "国外");
    }

    /**
     * 身份证验证
     * 
     * @param idCardNo
     * @return
     */
    public static String isValidCart(String idCardNo) {
        String[] ValCodeArr = { "1", "0", "x", "9", "8", "7", "6", "5", "4", "3", "2" };
        String[] Wi = { "7", "9", "10", "5", "8", "4", "2", "1", "6", "3", "7", "9", "10", "5", "8", "4", "2" };
        // String[] Checker = {"1","9","8","7","6","5","4","3","2","1","1"};
        String Ai = "";

        if (idCardNo == null || idCardNo.length() != 15 && idCardNo.length() != 18) {
            return "身份证号码长度错误。";
        }

        idCardNo = idCardNo.toLowerCase();

        // ================ 数字 除最后以为都为数字 ================
        if (idCardNo.length() == 18) {
            Ai = idCardNo.substring(0, 17);
        } else if (idCardNo.length() == 15) {
            Ai = idCardNo.substring(0, 6) + "19" + idCardNo.substring(6, 15);
        }
        if (!StringUtils.isNumeric(Ai)) {
            return "身份证号码中有不能识别的字符。"; // 15位号码都应为数字 ; 18位号码除最后一位外，都应为数字。";
        }

        // ================ 出生年月是否有效 ================
        String strYear = Ai.substring(6, 10);// 年份
        String strMonth = Ai.substring(10, 12);// 月份
        String strDay = Ai.substring(12, 14);// 月份

        if (isDate(strYear + "-" + strMonth + "-" + strDay) == false) {
            return "身份证错误"; // 生日无效。
        }

        GregorianCalendar gc = new GregorianCalendar();
        SimpleDateFormat s = new SimpleDateFormat("yyyy-MM-dd");

        Date d = null;
        try {
            d = s.parse(strYear + "-" + strMonth + "-" + strDay);
        } catch (ParseException e) {
            return "身份证错误";
        }

        if (d == null) {
            // 生日不在有效范围
            return "身份证错误";
        }

        if ((gc.get(Calendar.YEAR) - Integer.parseInt(strYear)) > 150 || (gc.getTime().getTime() - d.getTime()) < 0) {
            // 生日不在有效范围
            return "身份证错误";
        }
        if (Integer.parseInt(strMonth) > 12 || Integer.parseInt(strMonth) == 0) {
            // 月份无效
            return "身份证错误";
        }
        if (Integer.parseInt(strDay) > 31 || Integer.parseInt(strDay) == 0) {
            // 日期无效
            return "身份证错误";
        }

        // 地区码编码验证
        if (areaCode.get(Ai.substring(0, 2)) == null) {
            return "身份证错误"; // 地区编码错误
        }

        // 最后一位的值验证
        int totalmulAiWi = 0;
        for (int i = 0; i < 17; i++) {
            totalmulAiWi = totalmulAiWi + Integer.parseInt(String.valueOf(Ai.charAt(i))) * Integer.parseInt(Wi[i]);
        }

        int modValue = totalmulAiWi % 11;
        String strVerifyCode = ValCodeArr[modValue];
        Ai = Ai + strVerifyCode;

        if (idCardNo.length() == 18) {
            if (Ai.equals(idCardNo) == false) {
                return "身份证错误"; // "身份证无效，最后一位字母错误";
            }
        } else {
            // 所在地区:" + h.get(Ai.substring(0, 2).toString())
            // 新身份证号:" + Ai
            return "身份证错误";
        }

        return null;
    }

    static Pattern pattern = Pattern
            .compile("^((\\d{2}(([02468][048])|([13579][26]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])))))|(\\d{2}(([02468][1235679])|([13579][01345789]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|(1[0-9])|(2[0-8]))))))(\\s(((0?[0-9])|([1-2][0-3]))\\:([0-5]?[0-9])((\\s)|(\\:([0-5]?[0-9])))))?$");

    /**
     * 判断字符串是否为日期格式
     * 
     * @param str
     * @return
     */
    public static boolean isDate(String strDate) {
        return pattern.matcher(strDate).matches();
    }
    
    static Pattern pattern2 = Pattern.compile("^\\w+$");
    public static boolean isValidUserName(String username) {
        return pattern2.matcher(username).matches();
    }
    
    public static void main(String[] args) {
        System.out.println(isValidUserName("s"));
    }
}
